package stardust.product.platform.webc.container;


import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import stardust.product.platform.webc.RenderHandle;
import stardust.product.platform.webc.WebcCallback;
import stardust.product.platform.webc.WebcConfig;
import stardust.product.platform.webc.WebcException;
import stardust.product.platform.webc.WebcFilter;
import stardust.product.platform.webc.WebcResourceReference;
import stardust.product.platform.webc.support.StaticUrlUtils;


public class WebcContainer
{

  private WebcConfig config;

  private Map<String, WebcResourceReference> handleReference = new HashMap<String, WebcResourceReference>();
  
  private List<WebcCallback> callback = new ArrayList<WebcCallback>();

  private Map<String, RenderHandle> renderHandle = new HashMap<String, RenderHandle>();
  
  private List<WebcFilter> filter = new ArrayList<WebcFilter>();

  public WebcContainer(WebcConfig config)
  {
    this.config = config;
  }

  public List<WebcCallback> getCallback()
  {
    return this.callback;
  }

  public void registerCallback(Class<? extends WebcCallback> callback)
  {
    try
    {
      this.registerCallback(callback.newInstance());
    }
    catch(InstantiationException ex)
    {
      throw new WebcException("注册资源处理器[" + this.callback.getClass().getName() + "]失败。", ex);
    }
    catch(IllegalAccessException ex)
    {
      throw new WebcException("注册资源处理器[" + this.callback.getClass().getName() + "]失败。", ex);
    }
  }
  
  public void registerCallback(WebcCallback callback)
  {
    this.callback.add(0, callback);
  }
  
  public void registerRenderer(String name, RenderHandle r)
  {
    if (this.renderHandle.containsKey(name))
    {
      throw new WebcException("渲染器[" + name + "]已经被[" + this.renderHandle.get(name).getClass() + "]定义，无法重复注册。");
    }

    this.renderHandle.put(name, r);
  }

  public RenderHandle getRenderer(String name)
  {
    return this.renderHandle.get(name);
  }

  public void destroyRenderer(String name)
  {
    this.renderHandle.remove(name);
  }

  public void registerHandler(String uri, WebcResourceReference e)
  {
    if (this.handleReference.containsKey(uri))
    {
      throw new WebcException("资源[" + uri + "]已经在[" + this.handleReference.get(uri).getTargetMethod().toGenericString() + "]中定义，无法重复注册。");
    }
    
    /*
     * 检测RESTful URL多匹配冲突。
     */
    Iterator<String> i = this.handleReference.keySet().iterator();
    WebcResourceReference j;
    String srcUri;
    boolean srcRESTfulFlag;
    
    if (srcRESTfulFlag = e.isRESTfulURI())
    {
      srcUri = StaticUrlUtils.getMatchRegex(e.getUri());
    }
    else
    {
      srcUri = e.getUri();
    }
    
    while (i.hasNext())
    {
      j = this.handleReference.get(i.next());
      
      if ((srcRESTfulFlag && j.getUri().matches(srcUri)) || (!srcRESTfulFlag && j.isRESTfulURI() && srcUri.matches(StaticUrlUtils.getMatchRegex(j.getUri()))))
      {
        throw new WebcException("检测到隐性冲突，尝试注册的[" + uri + "]与[" + j.getUri() + "]的匹配模式可能重叠，这将导致访问二义性或发生覆盖，资源注册失败。");
      }
    }

    if (e.getInstance() == null)
    {
      try
      {
        e.setInstance(e.getTargetClass().newInstance());
      }
      catch(InstantiationException ex)
      {
        throw new WebcException("注册资源处理器[" + uri + "]失败。", ex);
      }
      catch(IllegalAccessException ex)
      {
        throw new WebcException("注册资源处理器[" + uri + "]失败。", ex);
      }
    }

    this.handleReference.put(uri, e);
  }

  public WebcResourceReference getHandler(String uri)
  {
    Iterator<String> i = this.handleReference.keySet().iterator();
    String key;
    WebcResourceReference reference;
    
    while (i.hasNext())
    {
      key = i.next();
      reference = this.handleReference.get(key);
      
      if (reference.getUri().equals(uri))
      {
        return reference;
      }
      else if (uri.matches(StaticUrlUtils.getMatchRegex(reference.getUri())))
      {
        return reference;
      }
    }
    
    return null;
  }
  
  public int getHandlerCount()
  {
    return this.handleReference.size();
  }

  public void destroyHandler(String uri)
  {
    this.handleReference.remove(uri);
  }
  
  public void registerFilter(Class<? extends WebcFilter> filter)
  {
    try
    {
      this.registerFilter(filter.newInstance());
    }
    catch (InstantiationException ex)
    {
      throw new WebcException("注册资源过滤器[" + filter.getClass().getName() + "]失败。", ex);
    }
    catch (IllegalAccessException ex)
    {
      throw new WebcException("注册资源过滤器[" + filter.getClass().getName() + "]失败。", ex);
    }
  }
  
  public void registerFilter(WebcFilter filter)
  {
    this.filter.add(filter);
  }
  
  public List<WebcFilter> getFilterQueue()
  {
    return this.filter;
  }
  
  public void destroyFilter(WebcFilter filter)
  {
    this.filter.remove(filter);
  }
  
  public Map<String, WebcResourceReference> getHandleReference()
  {
    return this.handleReference;
  }

  public Map<String, RenderHandle> getRenderHandle()
  {
    return this.renderHandle;
  }

  public WebcConfig getConfig()
  {
    return this.config;
  }

}
